/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_ui.htm
 *
 * Zhiqim UI is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
 
+(function(Z)
{//BEGIN 
// @version v1.1.0 @author zouzhigang 2015-11-12 新建与整理
        
// 调用举例:
// var ajax = new Z.Ajax();
// ajax.className = "org.zhiqim.ui.presenter.AjaxPresenter";
// ajax.methodName = "doQuery";
// ajax.params = [page];
// ajax.callback = function(){Z.alert(this.responseText);};
// ajax.execute();

Z.Ajax = Z.Class.newInstance();
Z.Ajax.v = "8.0.4";
Z.Ajax.prototype = 
{
    defaults: 
    {
        contextPath: null,          //指定上下文环境路径
        className: null,            //指定类名
        methodName: null,           //指定方法名
        token: "",                  //指定令牌字符串，后台验证
        async: true,                //指定是否异步，默认true, true|false
        params: [],                 //参数列表，通过addParam添加
        paramMap: new Z.HashMap(),  //参数Key-Value列表，通过addParam添加
        paramData: null,            //参数数据，如H5支持的FormData
        callback: null,             //回调函数或ID
        callbackMethod: "htmlc",     //回调ID时使用的方法，支持val|text|html|htmlc四种
        success: null,              //成功回调函数
        failure: null,              //失败回调函数
        
        //加载控件支持3种情况，1.函数，2.可执行对象如Z.loading，3.#ID(1.指定ID加载的HTML加载成功换回，2.指定ID上生成Z.loading)
        loading: null,              //加载控件回调函数或可执行对象或#ID
        loadingParam: null,         //加载控件参数，1.表示是否遮罩，2.#ID时指定的HTML，成功后换回原始HTML
        loadingAttr: null,          //加载控件属性
        loadingProcess: false,      //加载控件是否处理
        
        //响应结果
        responseStatus: 0,          //状态码,0表示正常，其他表示失败
        responseText: null          //状态字符串或返回结果字符串
    },
    
    init: function()
    {
        if (window.ActiveXObject)
        {// IE浏览器
            try {this.httpRequest = new ActiveXObject("Msxml2.XMLHTTP");}
            catch (e){try{this.httpRequest = new ActiveXObject("Microsoft.XMLHTTP");}catch (e){}}
        }
        else if(window.XMLHttpRequest)
        {//Mozilla 浏览器
            this.httpRequest = new XMLHttpRequest();
        }
    },
    
    execute: function()
    {
        if (!this.httpRequest) {Z.failure("[Z.Ajax]浏览器不支持AJAX");return false;}
        if (!this.className){Z.failure("[Z.Ajax]未设置className");return false;}
        if (!this.methodName){Z.failure("[Z.Ajax]未设置methodName");return false;}
        
        var requestPath = null;
        try {requestPath = window.location.pathname;}catch(e){requestPath = "null";}
        var requestUrl = Z.rootPath(this.contextPath, "/service/ajax?path="+requestPath+"&time="+(new Date()).getTime());
        
        var requestVar = null;
        if (this.paramMap.size() > 0 || this.paramData)
        {//参数键值对方式
            requestVar = "";
            if (this.paramMap.size() > 0)
            {//添加的键值
                Z.eachof(this, this.paramMap.keySet(), function(key){
                    requestVar += key + "=" + Z.encode(this.paramMap.get(key)) + "&";
                });
                
                requestVar = requestVar.slice(0, -1);
            }
            
            if (this.paramData)
            {//表单数据
                requestVar += "&" + this.paramData;
            }
        }
        else if (this.params.length > 0)
        {//参数列表方式
            requestVar = "";
            Z.eachof(this, this.params, function(param)
            {
                param = ""+param;
                if (param.indexOf('#') != -1)
                    param = param.replace(/\#/g, "-%2-%-3%-"); //把#先替换成-%2-%-3%-
                
                requestVar += "%23" + Z.encode(param) + "%23";
            });
        }
        
        if (this.async){
            this.httpRequest.onreadystatechange = Z.bind(this.receive, this);
        }
        this.httpRequest.open("POST", requestUrl, this.async);
        this.httpRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        this.httpRequest.setRequestHeader("X-RMI-Class", this.className);
        this.httpRequest.setRequestHeader("X-RMI-Method", this.methodName);
        if (this.token){
             this.httpRequest.setRequestHeader("X-RMI-Token", this.token);
        }
        if (this.paramMap.size() > 0 || this.paramData){
            this.httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        }else{
            this.httpRequest.setRequestHeader("Content-Type", "text/plain; charset=UTF-8");
        }
        this.httpRequest.send(requestVar);
        
        if (!this.async)
        {//同步处理结果
            this.processResult();
            return;
        }
        
        //异步处理
        if (!this.loading || (Z.Dialog && this.loading instanceof Z.Dialog))
        {//无加载器和对话框加载器不处理
            return;
        }
        
        //显示加载器，支持1.函数，2.可执行对象，3.#ID
        if (Z.T.isFunction(this.loading))
        {//函数直接调用
            this.loading.call(this);
        }
        else if (Z.T.isDocument(this.loading))
        {//全屏
            this.loading = Z.loading({target: document, shadow: true === this.loadingParam});
        }
        else if (Z.T.isElement(this.loading) || Z.T.isString(this.loading))
        {//#ID两种情况，1.指定ID的HTML内容，2.指定ID为加载目标范围
        
            if (Z.T.isString(this.loadingParam))
            {//ID上指定内容，则保留原HTML，换成加载中HTML
                var $loading = Z.T.isString(this.loading)?Z("#"+this.loading):Z(this.loading);
                
                var loadingTempHTML = $loading.html();
                $loading.html(this.loadingParam)
                this.loadingParam = loadingTempHTML;
                
                if (this.loadingAttr && this.loadingAttr.disabled === true)
                {
                    $loading.attr("disabled", true);
                }
                
            }
            else if (Z.loading)
            {//ID上指定ID为加载目标范围，则在ID上创建一个Z.loading对象
                this.loading = Z.loading({target: this.loading, shadow: true === this.loadingParam});
            }
        }
        else if (Z.T.isObject(this.loading) && this.loading.execute)
        {//可执行对象执行
            this.loading.execute();
        }
    },
    
    receive: function()
    {
        if (this.httpRequest.readyState != 4){
            return;
        }
        
        if (this.loading)
        {
            if (Z.T.isObject(this.loading) && this.loading.close)
            {//有关闭属性的对象，调用立即关闭
                this.loading.close(true);
            }
            else if ((Z.T.isString(this.loading) || Z.T.isElement(this.loading)) && this.loading != this.callback)
            {//ID上指定HTML，恢复成原HTML
                this.processRecoveryLoading();
            }
        }
        
        this.processResult();
    },
    
    processRecoveryLoading: function()
    {
        if (this.loadingProcess)
            return;
            
        var $loading = Z.T.isString(this.loading)?Z("#"+this.loading):Z(this.loading);
        if (!(this.loadingAttr && this.loadingAttr.recovery === false))
        {//默认恢复原HTML，除非指定不恢复
            if (this.loadingParam)
                $loading.html(this.loadingParam);
        }
        if (this.loadingAttr && this.loadingAttr.disabled === true && this.loadingAttr.recovery !== false)
        {//如果指定disable则恢复，除非指定不恢复
            $loading.attr("disabled", false);
        }
    },
    
    processResult: function()
    {
        if (this.httpRequest.status == 200)
        {//HTTP成功
            this.responseStatus = 0;
            this.responseText = this.httpRequest.responseText;
        }
        else
        {//HTTP失败sendError
            this.responseStatus = (this.httpRequest.status == 0)?91:this.httpRequest.status;
            this.responseText = this.httpRequest.responseText;
        }
        
        this.httpRequest = null;
        if (this.responseStatus >= 601 && this.responseStatus <= 603)
        {//有重定向要求
            var error;
            var ind = this.responseText.lastIndexOf("#");
            if (ind != -1)
            {//有错误信息
                error = this.responseText.substring(ind+1);
                this.responseText = this.responseText.substring(0, ind);
            }
            
            if (Z.V.isEmpty(error)){
                this.processRedirect();
            }else{//弹出提示信息后回调
                Z.failure(error, Z.bind(this.processRedirect, this));
            }

            throw "stop";//抛出异常防止后面的代码继续执行
        }
        else
        {
            if (this.responseStatus != 0 && Z.T.isFunction(this.failure))
            {//失败，优先找失败函数
                this.failure.call(this, this.responseText, this.responseStatus);
            }
            else if (this.responseStatus != 0 && Z.T.isString(this.failure))
            {//失败，再找失败ID
                this.showValue(this.failure);
            }
            else if (this.responseStatus == 0 && Z.T.isFunction(this.success))
            {//成功，优先找成功函数
                this.success.call(this, this.responseText, this.responseStatus);
            }
            else if (this.responseStatus == 0 && Z.T.isString(this.success))
            {//成功，再找成功ID
                this.showValue(this.success);
            }
            else if (Z.T.isFunction(this.callback))
            {//回调函数
                this.callback.call(this, this.responseText, this.responseStatus);
            }
            else if (Z.T.isString(this.callback))
            {//回调到ID上
                this.showValue(this.callback);
            }
        }
    },
    showValue: function(showId)
    {
        if (this.callbackMethod == "val")
            Z("#"+showId).val(this.responseText);
        else if (this.callbackMethod == "text")
            Z("#"+showId).text(this.responseText);
        else if (this.callbackMethod == "html")
            Z("#"+showId).html(this.responseText);
        else
            Z("#"+showId).htmlc(this.responseText);
    },
    processRedirect: function()
    {
        switch(this.responseStatus)
        {
            case 601:window.parent.location.href = this.responseText;break;
            case 602:window.location.href = this.responseText;break;
            case 603:window.top.location.href = this.responseText;break;
        }
    },
    
    /***************************************************/
    //以下为参数设置方法
    /***************************************************/
    
    setContextPath: function(_contextPath){this.contextPath = _contextPath;return this;},
    setClassName: function(_className){this.className = _className;return this;},
    setMethodName: function (_methodName){this.methodName = _methodName;return this;},
    setToken: function (_token){this.token = _token;return this;},
    setSync: function (){this.async = false;return this;},
    setCallback: function(_callback){this.callback = _callback;return this;},
    setCallbackMethod: function(_callbackMethod){this.callbackMethod = _callbackMethod;return this;},
    
    setSuccess: function(_success){this.success = _success;return this;},
    setSuccessLocation: function(_location, _target){this.success = function(){Z.L.href(_location, _target);};},
    setSuccessLocationResponse: function(_location, _target){this.success = function(){Z.L.href(this.responseText, _target);};},
    setSuccessReload: function(){this.success = function(){Z.L.reload();};},
    setSuccessReloadParent: function(){this.success = function(){parent.Z.L.reload();};},
    setSuccessReloadTop: function(){this.success = function(){top.Z.L.reload();};},
    setSuccessAlert: function(_text){this.success = function(){Z.success(_text||this.responseText||"提交成功");};return this;},
    setSuccessAlertLocation: function(_text, _location, _target){this.success = function(){Z.success(_text, function(){Z.L.href(_location, _target);});};},
    setSuccessAlertReload: function(_text){this.success = function(){Z.success(_text, function(){Z.L.reload()});};},
    setSuccessAlertReloadParent: function(_text){this.success = function(){Z.success(_text, function(){parent.Z.L.reload()});};},
    setSuccessAlertReloadTop: function(_text){this.success = function(){Z.success(_text, function(){top.Z.L.reload()});};},
    setFailure: function(_failure){this.failure = _failure;return this;},
    setFailureAlert: function(){this.failure = function(){Z.failure(this.responseText);};return this;},
    setFailureAlertRecovery: function(){this.failure = function(){if (this.loadingAttr){this.loadingAttr.recovery = true;this.processRecoveryLoading();}Z.failure(this.responseText);};return this;},
    
    addParam: function(_param, _param2){(_param2 == Z.u)?this.params.push(_param):this.paramMap.put(_param, _param2);return this;},
    setParamData: function(_paramData){this.paramData = _paramData;return this;},
    setParamForm: function(form){this.paramData = Z.FM.formData(form);return this;},

    //设置执行前等待函数或ID或对象
    setLoading: function(_loading, _loadingParam, _loadingAttr)
    {
        this.loading = _loading;
        this.loadingParam = _loadingParam;
        this.loadingAttr = _loadingAttr;
        return this;
    }
};

Z.ajax = function(clazz, method)
{//简写ajax
    var ajax = new Z.Ajax();
    ajax.setClassName(clazz);
    ajax.setMethodName(method);
    return ajax;
};

Z.ajaxq = function(clazz, method, page)
{//根据ajaxForm从后台查询HTML显示到ajaxqResult中
    var ajax = Z.ajax(clazz, method);
    ajax.addParam("page", page || 1);
    ajax.setParamForm(document.ajaxqForm);
    ajax.setFailureAlert();
    ajax.setSuccess("ajaxqResult");
    ajax.setLoading("ajaxqResult");
    ajax.execute();
};

Z.log = function(message, method)
{//打印日志到后台
    Z.ajax("Logs", method || "info").addParam(message).execute();
};

//END
})(zhiqim);